summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/general/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:18:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:18:41 +0000
commitb643c52cf29ce5bbab738b43290af3556efa1ca9 (patch)
tree21d5c53d7a9b696627a255777cefdf6f78968824 /ansible_collections/community/general/tests
parentReleasing progress-linux version 9.5.1+dfsg-1~progress7.99u1. (diff)
downloadansible-b643c52cf29ce5bbab738b43290af3556efa1ca9.tar.xz
ansible-b643c52cf29ce5bbab738b43290af3556efa1ca9.zip
Merging upstream version 10.0.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/general/tests')
-rw-r--r--ansible_collections/community/general/tests/integration/targets/callback_timestamp/aliases6
-rw-r--r--ansible_collections/community/general/tests/integration/targets/callback_timestamp/tasks/main.yml66
-rw-r--r--ansible_collections/community/general/tests/integration/targets/cpanm/tasks/main.yml3
-rw-r--r--ansible_collections/community/general/tests/integration/targets/django_manage/tasks/main.yaml5
-rw-r--r--ansible_collections/community/general/tests/integration/targets/ejabberd_user/tasks/main.yml3
-rw-r--r--ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/create_record.yml25
-rw-r--r--ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/update_record.yml24
-rw-r--r--ansible_collections/community/general/tests/integration/targets/homebrew/handlers/main.yml11
-rw-r--r--ansible_collections/community/general/tests/integration/targets/homebrew/tasks/casks.yml2
-rw-r--r--ansible_collections/community/general/tests/integration/targets/homebrew/tasks/docker.yml23
-rw-r--r--ansible_collections/community/general/tests/integration/targets/homebrew/tasks/formulae.yml2
-rw-r--r--ansible_collections/community/general/tests/integration/targets/homebrew/tasks/main.yml5
-rw-r--r--ansible_collections/community/general/tests/integration/targets/keycloak_identity_provider/tasks/main.yml1
-rwxr-xr-xansible_collections/community/general/tests/integration/targets/lookup_merge_variables/runme.sh3
-rw-r--r--ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/test_cross_host_merge_inventory.yml33
-rw-r--r--ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/test_cross_host_merge_play.yml21
-rw-r--r--ansible_collections/community/general/tests/integration/targets/module_helper/library/mdepfail.py5
-rw-r--r--ansible_collections/community/general/tests/integration/targets/module_helper/library/mstate.py1
-rw-r--r--ansible_collections/community/general/tests/integration/targets/snap/tasks/main.yml7
-rw-r--r--ansible_collections/community/general/tests/integration/targets/snap/tasks/test_channel.yml43
-rw-r--r--ansible_collections/community/general/tests/sanity/ignore-2.13.txt5
-rw-r--r--ansible_collections/community/general/tests/sanity/ignore-2.14.txt5
-rw-r--r--ansible_collections/community/general/tests/sanity/ignore-2.15.txt3
-rw-r--r--ansible_collections/community/general/tests/sanity/ignore-2.16.txt3
-rw-r--r--ansible_collections/community/general/tests/sanity/ignore-2.17.txt4
-rw-r--r--ansible_collections/community/general/tests/sanity/ignore-2.18.txt4
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/become/test_run0.py64
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/lookup/test_merge_variables.py182
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/module_utils/test_cmd_runner.py82
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/module_utils/test_python_runner.py223
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/modules/helper.py24
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/modules/test_cpanm.yaml5
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/modules/test_django_command.py13
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/modules/test_django_command.yaml38
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/modules/test_homebrew.py19
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/modules/test_puppet.yaml32
-rw-r--r--ansible_collections/community/general/tests/unit/plugins/plugin_utils/test_unsafe.py133
37 files changed, 918 insertions, 210 deletions
diff --git a/ansible_collections/community/general/tests/integration/targets/callback_timestamp/aliases b/ansible_collections/community/general/tests/integration/targets/callback_timestamp/aliases
new file mode 100644
index 000000000..124adcfb8
--- /dev/null
+++ b/ansible_collections/community/general/tests/integration/targets/callback_timestamp/aliases
@@ -0,0 +1,6 @@
+# Copyright (c) 2024, kurokobo <kurokobo@protonmail.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
+
+azp/posix/1
+needs/target/callback
diff --git a/ansible_collections/community/general/tests/integration/targets/callback_timestamp/tasks/main.yml b/ansible_collections/community/general/tests/integration/targets/callback_timestamp/tasks/main.yml
new file mode 100644
index 000000000..5e0acc15f
--- /dev/null
+++ b/ansible_collections/community/general/tests/integration/targets/callback_timestamp/tasks/main.yml
@@ -0,0 +1,66 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+# Copyright (c) 2024, kurokobo <kurokobo@protonmail.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
+
+- name: Run tests
+ include_role:
+ name: callback
+ vars:
+ tests:
+ - name: Enable timestamp in the default length
+ environment:
+ ANSIBLE_NOCOLOR: 'true'
+ ANSIBLE_FORCE_COLOR: 'false'
+ ANSIBLE_STDOUT_CALLBACK: community.general.timestamp
+ ANSIBLE_CALLBACK_TIMESTAMP_FORMAT_STRING: "15:04:05"
+ playbook: |
+ - hosts: testhost
+ gather_facts: false
+ tasks:
+ - name: Sample task name
+ debug:
+ msg: sample debug msg
+ expected_output: [
+ "",
+ "PLAY [testhost] ******************************************************* 15:04:05",
+ "",
+ "TASK [Sample task name] *********************************************** 15:04:05",
+ "ok: [testhost] => {",
+ " \"msg\": \"sample debug msg\"",
+ "}",
+ "",
+ "PLAY RECAP ************************************************************ 15:04:05",
+ "testhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 "
+ ]
+
+ - name: Enable timestamp in the longer length
+ environment:
+ ANSIBLE_NOCOLOR: 'true'
+ ANSIBLE_FORCE_COLOR: 'false'
+ ANSIBLE_STDOUT_CALLBACK: community.general.timestamp
+ ANSIBLE_CALLBACK_TIMESTAMP_FORMAT_STRING: "2006-01-02T15:04:05"
+ playbook: |
+ - hosts: testhost
+ gather_facts: false
+ tasks:
+ - name: Sample task name
+ debug:
+ msg: sample debug msg
+ expected_output: [
+ "",
+ "PLAY [testhost] ******************************************** 2006-01-02T15:04:05",
+ "",
+ "TASK [Sample task name] ************************************ 2006-01-02T15:04:05",
+ "ok: [testhost] => {",
+ " \"msg\": \"sample debug msg\"",
+ "}",
+ "",
+ "PLAY RECAP ************************************************* 2006-01-02T15:04:05",
+ "testhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 "
+ ]
diff --git a/ansible_collections/community/general/tests/integration/targets/cpanm/tasks/main.yml b/ansible_collections/community/general/tests/integration/targets/cpanm/tasks/main.yml
index c9adc1ca6..89650154f 100644
--- a/ansible_collections/community/general/tests/integration/targets/cpanm/tasks/main.yml
+++ b/ansible_collections/community/general/tests/integration/targets/cpanm/tasks/main.yml
@@ -6,7 +6,8 @@
- name: bail out for non-supported platforms
meta: end_play
when:
- - (ansible_os_family != "RedHat" or ansible_distribution_major_version|int < 7)
+ - (ansible_os_family != "RedHat" or ansible_distribution_major_version|int < 8) # TODO: bump back to 7
+ - (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int < 8) # TODO: remove
- ansible_os_family != "Debian"
- name: install perl development package for Red Hat family
diff --git a/ansible_collections/community/general/tests/integration/targets/django_manage/tasks/main.yaml b/ansible_collections/community/general/tests/integration/targets/django_manage/tasks/main.yaml
index c07b53893..5307fb664 100644
--- a/ansible_collections/community/general/tests/integration/targets/django_manage/tasks/main.yaml
+++ b/ansible_collections/community/general/tests/integration/targets/django_manage/tasks/main.yaml
@@ -43,6 +43,11 @@
chdir: "{{ tmp_django_root.path }}/startproj"
cmd: "{{ tmp_django_root.path }}/venv/bin/django-admin startapp app1"
+- name: Make manage.py executable
+ file:
+ path: "{{ tmp_django_root.path }}/startproj/test_django_manage_1/manage.py"
+ mode: "0755"
+
- name: Check
community.general.django_manage:
project_path: "{{ tmp_django_root.path }}/startproj/test_django_manage_1"
diff --git a/ansible_collections/community/general/tests/integration/targets/ejabberd_user/tasks/main.yml b/ansible_collections/community/general/tests/integration/targets/ejabberd_user/tasks/main.yml
index 33e07b785..349b3f952 100644
--- a/ansible_collections/community/general/tests/integration/targets/ejabberd_user/tasks/main.yml
+++ b/ansible_collections/community/general/tests/integration/targets/ejabberd_user/tasks/main.yml
@@ -10,7 +10,8 @@
- name: Bail out if not supported
ansible.builtin.meta: end_play
- when: ansible_distribution in ('Alpine', 'openSUSE Leap', 'CentOS', 'Fedora')
+ # TODO: remove Archlinux from the list
+ when: ansible_distribution in ('Alpine', 'openSUSE Leap', 'CentOS', 'Fedora', 'Archlinux')
- name: Remove ejabberd
diff --git a/ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/create_record.yml b/ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/create_record.yml
index c3f1c1798..87056aa86 100644
--- a/ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/create_record.yml
+++ b/ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/create_record.yml
@@ -45,10 +45,10 @@
assert:
that:
- result is changed
- - result.record['values'] == {{ item['values'] }}
- - result.record.record == "{{ item.record }}"
- - result.record.type == "{{ item.type }}"
- - result.record.ttl == {{ item.ttl }}
+ - result.record['values'] == item['values']
+ - result.record.record == item.record
+ - result.record.type == item.type
+ - result.record.ttl == item.ttl
- name: test create a dns record idempotence
community.general.gandi_livedns:
@@ -63,7 +63,16 @@
assert:
that:
- result is not changed
- - result.record['values'] == {{ item['values'] }}
- - result.record.record == "{{ item.record }}"
- - result.record.type == "{{ item.type }}"
- - result.record.ttl == {{ item.ttl }}
+ - result.record['values'] == item['values']
+ - result.record.record == item.record
+ - result.record.type == item.type
+ - result.record.ttl == item.ttl
+
+- name: test create a DNS record with personal access token
+ community.general.gandi_livedns:
+ personal_access_token: "{{ gandi_personal_access_token }}"
+ record: "{{ item.record }}"
+ domain: "{{ gandi_livedns_domain_name }}"
+ values: "{{ item['values'] }}"
+ ttl: "{{ item.ttl }}"
+ type: "{{ item.type }}"
diff --git a/ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/update_record.yml b/ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/update_record.yml
index a080560a7..5f19bfa24 100644
--- a/ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/update_record.yml
+++ b/ansible_collections/community/general/tests/integration/targets/gandi_livedns/tasks/update_record.yml
@@ -17,10 +17,10 @@
assert:
that:
- result is changed
- - result.record['values'] == {{ item.update_values | default(item['values']) }}
- - result.record.record == "{{ item.record }}"
- - result.record.type == "{{ item.type }}"
- - result.record.ttl == {{ item.update_ttl | default(item.ttl) }}
+ - result.record['values'] == (item.update_values | default(item['values']))
+ - result.record.record == item.record
+ - result.record.type == item.type
+ - result.record.ttl == (item.update_ttl | default(item.ttl))
- name: test update or add another dns record
community.general.gandi_livedns:
@@ -35,10 +35,10 @@
assert:
that:
- result is changed
- - result.record['values'] == {{ item.update_values | default(item['values']) }}
- - result.record.record == "{{ item.record }}"
- - result.record.ttl == {{ item.update_ttl | default(item.ttl) }}
- - result.record.type == "{{ item.type }}"
+ - result.record['values'] == (item.update_values | default(item['values']))
+ - result.record.record == item.record
+ - result.record.ttl == (item.update_ttl | default(item.ttl))
+ - result.record.type == item.type
- name: test update or add another dns record idempotence
community.general.gandi_livedns:
@@ -53,7 +53,7 @@
assert:
that:
- result is not changed
- - result.record['values'] == {{ item.update_values | default(item['values']) }}
- - result.record.record == "{{ item.record }}"
- - result.record.ttl == {{ item.update_ttl | default(item.ttl) }}
- - result.record.type == "{{ item.type }}"
+ - result.record['values'] == (item.update_values | default(item['values']))
+ - result.record.record == item.record
+ - result.record.ttl == (item.update_ttl | default(item.ttl))
+ - result.record.type == item.type
diff --git a/ansible_collections/community/general/tests/integration/targets/homebrew/handlers/main.yml b/ansible_collections/community/general/tests/integration/targets/homebrew/handlers/main.yml
new file mode 100644
index 000000000..90a2e8017
--- /dev/null
+++ b/ansible_collections/community/general/tests/integration/targets/homebrew/handlers/main.yml
@@ -0,0 +1,11 @@
+---
+# 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: uninstall docker
+ community.general.homebrew:
+ name: docker
+ state: absent
+ become: true
+ become_user: "{{ brew_stat.stat.pw_name }}"
diff --git a/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/casks.yml b/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/casks.yml
index 42d3515bf..ffbe67d15 100644
--- a/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/casks.yml
+++ b/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/casks.yml
@@ -12,13 +12,11 @@
- name: Find brew binary
command: which brew
register: brew_which
- when: ansible_distribution in ['MacOSX']
- name: Get owner of brew binary
stat:
path: "{{ brew_which.stdout }}"
register: brew_stat
- when: ansible_distribution in ['MacOSX']
#- name: Use ignored-pinned option while upgrading all
# homebrew:
diff --git a/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/docker.yml b/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/docker.yml
new file mode 100644
index 000000000..c7f282ba2
--- /dev/null
+++ b/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/docker.yml
@@ -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: MACOS | Find brew binary
+ command: which brew
+ register: brew_which
+
+- name: MACOS | Get owner of brew binary
+ stat:
+ path: "{{ brew_which.stdout }}"
+ register: brew_stat
+
+- name: MACOS | Install docker
+ community.general.homebrew:
+ name: docker
+ state: present
+ force_formula: true
+ become: true
+ become_user: "{{ brew_stat.stat.pw_name }}"
+ notify:
+ - uninstall docker
diff --git a/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/formulae.yml b/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/formulae.yml
index 1db3ef1a6..1ca8d753e 100644
--- a/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/formulae.yml
+++ b/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/formulae.yml
@@ -12,13 +12,11 @@
- name: Find brew binary
command: which brew
register: brew_which
- when: ansible_distribution in ['MacOSX']
- name: Get owner of brew binary
stat:
path: "{{ brew_which.stdout }}"
register: brew_stat
- when: ansible_distribution in ['MacOSX']
#- name: Use ignored-pinned option while upgrading all
# homebrew:
diff --git a/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/main.yml b/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/main.yml
index f5479917e..00d0bcf31 100644
--- a/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/main.yml
+++ b/ansible_collections/community/general/tests/integration/targets/homebrew/tasks/main.yml
@@ -9,9 +9,8 @@
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
-- block:
- - include_tasks: 'formulae.yml'
-
- when: ansible_distribution in ['MacOSX']
block:
+ - include_tasks: 'formulae.yml'
- include_tasks: 'casks.yml'
+ - include_tasks: 'docker.yml'
diff --git a/ansible_collections/community/general/tests/integration/targets/keycloak_identity_provider/tasks/main.yml b/ansible_collections/community/general/tests/integration/targets/keycloak_identity_provider/tasks/main.yml
index afad9740e..fa118ed1d 100644
--- a/ansible_collections/community/general/tests/integration/targets/keycloak_identity_provider/tasks/main.yml
+++ b/ansible_collections/community/general/tests/integration/targets/keycloak_identity_provider/tasks/main.yml
@@ -62,6 +62,7 @@
- result.existing == {}
- result.end_state.alias == "{{ idp }}"
- result.end_state.mappers != []
+ - result.end_state.config.client_secret = "**********"
- name: Update existing identity provider (no change)
community.general.keycloak_identity_provider:
diff --git a/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/runme.sh b/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/runme.sh
index 4e66476be..ada6908dd 100755
--- a/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/runme.sh
+++ b/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/runme.sh
@@ -14,3 +14,6 @@ ANSIBLE_MERGE_VARIABLES_PATTERN_TYPE=suffix \
ANSIBLE_LOG_PATH=/tmp/ansible-test-merge-variables \
ansible-playbook -i test_inventory_all_hosts.yml test_all_hosts.yml "$@"
+
+ANSIBLE_LOG_PATH=/tmp/ansible-test-merge-variables \
+ ansible-playbook -i test_cross_host_merge_inventory.yml test_cross_host_merge_play.yml "$@"
diff --git a/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/test_cross_host_merge_inventory.yml b/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/test_cross_host_merge_inventory.yml
new file mode 100644
index 000000000..938457023
--- /dev/null
+++ b/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/test_cross_host_merge_inventory.yml
@@ -0,0 +1,33 @@
+---
+# Copyright (c) 2020, Thales Netherlands
+# Copyright (c) 2021, 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
+
+common:
+ vars:
+ provider_instances:
+ servicedata1:
+ host: "{{ hostvars[groups['provider'] | first].inventory_hostname }}"
+ user: usr
+ pass: pwd
+ servicedata2:
+ host: down
+ user: usr2
+ pass: pwd2
+ hosts:
+ host1:
+ host2:
+
+consumer:
+ vars:
+ service_data: "{{ provider_instances.servicedata1 }}"
+ merge2__1: "{{ service_data }}" # service_data is a variable only known to host2, so normally it´s not available for host1 that is performing the merge
+ hosts:
+ host2:
+
+provider:
+ vars:
+ merge_result: "{{ lookup('community.general.merge_variables', 'merge2__', pattern_type='prefix', groups=['consumer']) }}"
+ hosts:
+ host1:
diff --git a/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/test_cross_host_merge_play.yml b/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/test_cross_host_merge_play.yml
new file mode 100644
index 000000000..51cd6f1ba
--- /dev/null
+++ b/ansible_collections/community/general/tests/integration/targets/lookup_merge_variables/test_cross_host_merge_play.yml
@@ -0,0 +1,21 @@
+---
+# Copyright (c) 2020, Thales Netherlands
+# Copyright (c) 2021, 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: Test merge_variables lookup plugin (merging host reference variables)
+ hosts: host1
+ connection: local
+ gather_facts: false
+ tasks:
+ - name: Print merge result
+ ansible.builtin.debug:
+ msg: "{{ merge_result }}"
+ - name: Validate merge result
+ ansible.builtin.assert:
+ that:
+ - "merge_result | length == 3"
+ - "merge_result.host == 'host1'"
+ - "merge_result.user == 'usr'"
+ - "merge_result.pass == 'pwd'"
diff --git a/ansible_collections/community/general/tests/integration/targets/module_helper/library/mdepfail.py b/ansible_collections/community/general/tests/integration/targets/module_helper/library/mdepfail.py
index 92ebbde6e..b61c32a4d 100644
--- a/ansible_collections/community/general/tests/integration/targets/module_helper/library/mdepfail.py
+++ b/ansible_collections/community/general/tests/integration/targets/module_helper/library/mdepfail.py
@@ -30,10 +30,10 @@ EXAMPLES = ""
RETURN = ""
+from ansible_collections.community.general.plugins.module_utils import deps
from ansible_collections.community.general.plugins.module_utils.module_helper import ModuleHelper
-from ansible.module_utils.basic import missing_required_lib
-with ModuleHelper.dependency("nopackagewiththisname", missing_required_lib("nopackagewiththisname")):
+with deps.declare("nopackagewiththisname"):
import nopackagewiththisname # noqa: F401, pylint: disable=unused-import
@@ -50,6 +50,7 @@ class MSimple(ModuleHelper):
def __init_module__(self):
self.vars.set('value', None)
self.vars.set('abc', "abc", diff=True)
+ deps.validate(self.module)
def __run__(self):
if (0 if self.vars.a is None else self.vars.a) >= 100:
diff --git a/ansible_collections/community/general/tests/integration/targets/module_helper/library/mstate.py b/ansible_collections/community/general/tests/integration/targets/module_helper/library/mstate.py
index bfaab0375..b3b4ed5e6 100644
--- a/ansible_collections/community/general/tests/integration/targets/module_helper/library/mstate.py
+++ b/ansible_collections/community/general/tests/integration/targets/module_helper/library/mstate.py
@@ -49,6 +49,7 @@ class MState(StateModuleHelper):
state=dict(type='str', choices=['join', 'b_x_a', 'c_x_a', 'both_x_a', 'nop'], default='join'),
),
)
+ use_old_vardict = False
def __init_module__(self):
self.vars.set('result', "abc", diff=True)
diff --git a/ansible_collections/community/general/tests/integration/targets/snap/tasks/main.yml b/ansible_collections/community/general/tests/integration/targets/snap/tasks/main.yml
index 2a683617a..a2d8698d0 100644
--- a/ansible_collections/community/general/tests/integration/targets/snap/tasks/main.yml
+++ b/ansible_collections/community/general/tests/integration/targets/snap/tasks/main.yml
@@ -13,10 +13,9 @@
block:
- name: Include test
ansible.builtin.include_tasks: test.yml
- # TODO: Find better package to install from a channel - microk8s installation takes multiple minutes, and even removal takes one minute!
- # - name: Include test_channel
- # ansible.builtin.include_tasks: test_channel.yml
- # TODO: Find bettter package to download and install from sources - cider 1.6.0 takes over 35 seconds to install
+ - name: Include test_channel
+ ansible.builtin.include_tasks: test_channel.yml
+ # TODO: Find better package to download and install from sources - cider 1.6.0 takes over 35 seconds to install
# - name: Include test_dangerous
# ansible.builtin.include_tasks: test_dangerous.yml
- name: Include test_3dash
diff --git a/ansible_collections/community/general/tests/integration/targets/snap/tasks/test_channel.yml b/ansible_collections/community/general/tests/integration/targets/snap/tasks/test_channel.yml
index e9eb19c89..353735761 100644
--- a/ansible_collections/community/general/tests/integration/targets/snap/tasks/test_channel.yml
+++ b/ansible_collections/community/general/tests/integration/targets/snap/tasks/test_channel.yml
@@ -5,47 +5,44 @@
# NOTE This is currently disabled for performance reasons!
-- name: Make sure package is not installed (microk8s)
+- name: Make sure package is not installed (wisdom)
community.general.snap:
- name: microk8s
+ name: wisdom
state: absent
# Test for https://github.com/ansible-collections/community.general/issues/1606
-- name: Install package (microk8s)
+- name: Install package (wisdom)
community.general.snap:
- name: microk8s
- classic: true
+ name: wisdom
state: present
- register: install_microk8s
+ register: install_wisdom
-- name: Install package with channel (microk8s)
+- name: Install package with channel (wisdom)
community.general.snap:
- name: microk8s
- classic: true
- channel: 1.20/stable
+ name: wisdom
state: present
- register: install_microk8s_chan
+ channel: latest/edge
+ register: install_wisdom_chan
-- name: Install package with channel (microk8s) again
+- name: Install package with channel (wisdom) again
community.general.snap:
- name: microk8s
- classic: true
- channel: 1.20/stable
+ name: wisdom
state: present
- register: install_microk8s_chan_again
+ channel: latest/edge
+ register: install_wisdom_chan_again
-- name: Remove package (microk8s)
+- name: Remove package (wisdom)
community.general.snap:
- name: microk8s
+ name: wisdom
state: absent
- register: remove_microk8s
+ register: remove_wisdom
- assert:
that:
- - install_microk8s is changed
- - install_microk8s_chan is changed
- - install_microk8s_chan_again is not changed
- - remove_microk8s is changed
+ - install_wisdom is changed
+ - install_wisdom_chan is changed
+ - install_wisdom_chan_again is not changed
+ - remove_wisdom is changed
- name: Install package (shellcheck)
community.general.snap:
diff --git a/ansible_collections/community/general/tests/sanity/ignore-2.13.txt b/ansible_collections/community/general/tests/sanity/ignore-2.13.txt
index 0665ddc1a..6f6495dd1 100644
--- a/ansible_collections/community/general/tests/sanity/ignore-2.13.txt
+++ b/ansible_collections/community/general/tests/sanity/ignore-2.13.txt
@@ -1,4 +1,6 @@
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
+plugins/callback/timestamp.py validate-modules:invalid-documentation
+plugins/callback/yaml.py validate-modules:invalid-documentation
plugins/lookup/etcd.py validate-modules:invalid-documentation
plugins/lookup/etcd3.py validate-modules:invalid-documentation
plugins/modules/consul_session.py validate-modules:parameter-state-invalid-choice
@@ -6,9 +8,6 @@ plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/osx_defaults.py validate-modules:parameter-state-invalid-choice
plugins/modules/parted.py validate-modules:parameter-state-invalid-choice
-plugins/modules/rax_files_objects.py use-argspec-type-path # module deprecated - removed in 9.0.0
-plugins/modules/rax_files.py validate-modules:parameter-state-invalid-choice # module deprecated - removed in 9.0.0
-plugins/modules/rax.py use-argspec-type-path # module deprecated - removed in 9.0.0
plugins/modules/read_csv.py validate-modules:invalid-documentation
plugins/modules/rhevm.py validate-modules:parameter-state-invalid-choice
plugins/modules/xfconf.py validate-modules:return-syntax-error
diff --git a/ansible_collections/community/general/tests/sanity/ignore-2.14.txt b/ansible_collections/community/general/tests/sanity/ignore-2.14.txt
index fed147e44..24d752103 100644
--- a/ansible_collections/community/general/tests/sanity/ignore-2.14.txt
+++ b/ansible_collections/community/general/tests/sanity/ignore-2.14.txt
@@ -1,4 +1,6 @@
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
+plugins/callback/timestamp.py validate-modules:invalid-documentation
+plugins/callback/yaml.py validate-modules:invalid-documentation
plugins/lookup/etcd.py validate-modules:invalid-documentation
plugins/lookup/etcd3.py validate-modules:invalid-documentation
plugins/modules/consul_session.py validate-modules:parameter-state-invalid-choice
@@ -7,9 +9,6 @@ plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/osx_defaults.py validate-modules:parameter-state-invalid-choice
plugins/modules/parted.py validate-modules:parameter-state-invalid-choice
-plugins/modules/rax_files_objects.py use-argspec-type-path # module deprecated - removed in 9.0.0
-plugins/modules/rax_files.py validate-modules:parameter-state-invalid-choice # module deprecated - removed in 9.0.0
-plugins/modules/rax.py use-argspec-type-path # module deprecated - removed in 9.0.0
plugins/modules/read_csv.py validate-modules:invalid-documentation
plugins/modules/rhevm.py validate-modules:parameter-state-invalid-choice
plugins/modules/udm_user.py import-3.11 # Uses deprecated stdlib library 'crypt'
diff --git a/ansible_collections/community/general/tests/sanity/ignore-2.15.txt b/ansible_collections/community/general/tests/sanity/ignore-2.15.txt
index d4c92c4d9..667c6cee4 100644
--- a/ansible_collections/community/general/tests/sanity/ignore-2.15.txt
+++ b/ansible_collections/community/general/tests/sanity/ignore-2.15.txt
@@ -5,9 +5,6 @@ plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/osx_defaults.py validate-modules:parameter-state-invalid-choice
plugins/modules/parted.py validate-modules:parameter-state-invalid-choice
-plugins/modules/rax_files_objects.py use-argspec-type-path # module deprecated - removed in 9.0.0
-plugins/modules/rax_files.py validate-modules:parameter-state-invalid-choice # module deprecated - removed in 9.0.0
-plugins/modules/rax.py use-argspec-type-path # module deprecated - removed in 9.0.0
plugins/modules/rhevm.py validate-modules:parameter-state-invalid-choice
plugins/modules/udm_user.py import-3.11 # Uses deprecated stdlib library 'crypt'
plugins/modules/xfconf.py validate-modules:return-syntax-error
diff --git a/ansible_collections/community/general/tests/sanity/ignore-2.16.txt b/ansible_collections/community/general/tests/sanity/ignore-2.16.txt
index 397c6d986..f6b058ec6 100644
--- a/ansible_collections/community/general/tests/sanity/ignore-2.16.txt
+++ b/ansible_collections/community/general/tests/sanity/ignore-2.16.txt
@@ -5,9 +5,6 @@ plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/osx_defaults.py validate-modules:parameter-state-invalid-choice
plugins/modules/parted.py validate-modules:parameter-state-invalid-choice
-plugins/modules/rax_files_objects.py use-argspec-type-path # module deprecated - removed in 9.0.0
-plugins/modules/rax_files.py validate-modules:parameter-state-invalid-choice # module deprecated - removed in 9.0.0
-plugins/modules/rax.py use-argspec-type-path # module deprecated - removed in 9.0.0
plugins/modules/rhevm.py validate-modules:parameter-state-invalid-choice
plugins/modules/udm_user.py import-3.11 # Uses deprecated stdlib library 'crypt'
plugins/modules/udm_user.py import-3.12 # Uses deprecated stdlib library 'crypt'
diff --git a/ansible_collections/community/general/tests/sanity/ignore-2.17.txt b/ansible_collections/community/general/tests/sanity/ignore-2.17.txt
index d75aaeac2..806c4c5fc 100644
--- a/ansible_collections/community/general/tests/sanity/ignore-2.17.txt
+++ b/ansible_collections/community/general/tests/sanity/ignore-2.17.txt
@@ -5,13 +5,11 @@ plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/osx_defaults.py validate-modules:parameter-state-invalid-choice
plugins/modules/parted.py validate-modules:parameter-state-invalid-choice
-plugins/modules/rax_files_objects.py use-argspec-type-path # module deprecated - removed in 9.0.0
-plugins/modules/rax_files.py validate-modules:parameter-state-invalid-choice # module deprecated - removed in 9.0.0
-plugins/modules/rax.py use-argspec-type-path # module deprecated - removed in 9.0.0
plugins/modules/rhevm.py validate-modules:parameter-state-invalid-choice
plugins/modules/udm_user.py import-3.11 # Uses deprecated stdlib library 'crypt'
plugins/modules/udm_user.py import-3.12 # Uses deprecated stdlib library 'crypt'
plugins/modules/xfconf.py validate-modules:return-syntax-error
plugins/module_utils/univention_umc.py pylint:use-yield-from # suggested construct does not work with Python 2
tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2
+tests/unit/plugins/modules/helper.py pylint:use-yield-from # suggested construct does not work with Python 2
tests/unit/plugins/modules/test_gio_mime.yaml no-smart-quotes
diff --git a/ansible_collections/community/general/tests/sanity/ignore-2.18.txt b/ansible_collections/community/general/tests/sanity/ignore-2.18.txt
index d75aaeac2..806c4c5fc 100644
--- a/ansible_collections/community/general/tests/sanity/ignore-2.18.txt
+++ b/ansible_collections/community/general/tests/sanity/ignore-2.18.txt
@@ -5,13 +5,11 @@ plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/osx_defaults.py validate-modules:parameter-state-invalid-choice
plugins/modules/parted.py validate-modules:parameter-state-invalid-choice
-plugins/modules/rax_files_objects.py use-argspec-type-path # module deprecated - removed in 9.0.0
-plugins/modules/rax_files.py validate-modules:parameter-state-invalid-choice # module deprecated - removed in 9.0.0
-plugins/modules/rax.py use-argspec-type-path # module deprecated - removed in 9.0.0
plugins/modules/rhevm.py validate-modules:parameter-state-invalid-choice
plugins/modules/udm_user.py import-3.11 # Uses deprecated stdlib library 'crypt'
plugins/modules/udm_user.py import-3.12 # Uses deprecated stdlib library 'crypt'
plugins/modules/xfconf.py validate-modules:return-syntax-error
plugins/module_utils/univention_umc.py pylint:use-yield-from # suggested construct does not work with Python 2
tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2
+tests/unit/plugins/modules/helper.py pylint:use-yield-from # suggested construct does not work with Python 2
tests/unit/plugins/modules/test_gio_mime.yaml no-smart-quotes
diff --git a/ansible_collections/community/general/tests/unit/plugins/become/test_run0.py b/ansible_collections/community/general/tests/unit/plugins/become/test_run0.py
new file mode 100644
index 000000000..7507c556e
--- /dev/null
+++ b/ansible_collections/community/general/tests/unit/plugins/become/test_run0.py
@@ -0,0 +1,64 @@
+# Copyright (c) 2024 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
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import re
+
+from ansible import context
+
+from .helper import call_become_plugin
+
+
+def test_run0_basic(mocker, parser, reset_cli_args):
+ options = parser.parse_args([])
+ context._init_global_context(options)
+
+ default_cmd = "/bin/foo"
+ default_exe = "/bin/sh"
+ run0_exe = "run0"
+
+ success = "BECOME-SUCCESS-.+?"
+
+ task = {
+ "become_method": "community.general.run0",
+ }
+ var_options = {}
+ cmd = call_become_plugin(task, var_options, cmd=default_cmd, executable=default_exe)
+ assert (
+ re.match(
+ f"{run0_exe} --user=root {default_exe} -c 'echo {success}; {default_cmd}'",
+ cmd,
+ )
+ is not None
+ )
+
+
+def test_run0_flags(mocker, parser, reset_cli_args):
+ options = parser.parse_args([])
+ context._init_global_context(options)
+
+ default_cmd = "/bin/foo"
+ default_exe = "/bin/sh"
+ run0_exe = "run0"
+ run0_flags = "--nice=15"
+
+ success = "BECOME-SUCCESS-.+?"
+
+ task = {
+ "become_method": "community.general.run0",
+ "become_flags": run0_flags,
+ }
+ var_options = {}
+ cmd = call_become_plugin(task, var_options, cmd=default_cmd, executable=default_exe)
+ assert (
+ re.match(
+ f"{run0_exe} --user=root --nice=15 {default_exe} -c 'echo {success}; {default_cmd}'",
+ cmd,
+ )
+ is not None
+ )
diff --git a/ansible_collections/community/general/tests/unit/plugins/lookup/test_merge_variables.py b/ansible_collections/community/general/tests/unit/plugins/lookup/test_merge_variables.py
index 66cb2f08b..ba8209439 100644
--- a/ansible_collections/community/general/tests/unit/plugins/lookup/test_merge_variables.py
+++ b/ansible_collections/community/general/tests/unit/plugins/lookup/test_merge_variables.py
@@ -18,6 +18,17 @@ from ansible_collections.community.general.plugins.lookup import merge_variables
class TestMergeVariablesLookup(unittest.TestCase):
+ class HostVarsMock(dict):
+
+ def __getattr__(self, item):
+ return super().__getitem__(item)
+
+ def __setattr__(self, item, value):
+ return super().__setitem__(item, value)
+
+ def raw_get(self, host):
+ return super().__getitem__(host)
+
def setUp(self):
self.loader = DictDataLoader({})
self.templar = Templar(loader=self.loader, variables={})
@@ -141,25 +152,28 @@ class TestMergeVariablesLookup(unittest.TestCase):
{'var': [{'item5': 'value5', 'item6': 'value6'}]},
])
def test_merge_dict_group_all(self, mock_set_options, mock_get_option, mock_template):
- results = self.merge_vars_lookup.run(['__merge_var'], {
- 'inventory_hostname': 'host1',
- 'hostvars': {
- 'host1': {
- 'group_names': ['dummy1'],
- 'inventory_hostname': 'host1',
- '1testlist__merge_var': {
- 'var': [{'item1': 'value1', 'item2': 'value2'}]
- }
- },
- 'host2': {
- 'group_names': ['dummy1'],
- 'inventory_hostname': 'host2',
- '2otherlist__merge_var': {
- 'var': [{'item5': 'value5', 'item6': 'value6'}]
- }
+ hostvars = self.HostVarsMock({
+ 'host1': {
+ 'group_names': ['dummy1'],
+ 'inventory_hostname': 'host1',
+ '1testlist__merge_var': {
+ 'var': [{'item1': 'value1', 'item2': 'value2'}]
+ }
+ },
+ 'host2': {
+ 'group_names': ['dummy1'],
+ 'inventory_hostname': 'host2',
+ '2otherlist__merge_var': {
+ 'var': [{'item5': 'value5', 'item6': 'value6'}]
}
}
})
+ variables = {
+ 'inventory_hostname': 'host1',
+ 'hostvars': hostvars
+ }
+
+ results = self.merge_vars_lookup.run(['__merge_var'], variables)
self.assertEqual(results, [
{'var': [
@@ -175,32 +189,35 @@ class TestMergeVariablesLookup(unittest.TestCase):
{'var': [{'item5': 'value5', 'item6': 'value6'}]},
])
def test_merge_dict_group_single(self, mock_set_options, mock_get_option, mock_template):
- results = self.merge_vars_lookup.run(['__merge_var'], {
- 'inventory_hostname': 'host1',
- 'hostvars': {
- 'host1': {
- 'group_names': ['dummy1'],
- 'inventory_hostname': 'host1',
- '1testlist__merge_var': {
- 'var': [{'item1': 'value1', 'item2': 'value2'}]
- }
- },
- 'host2': {
- 'group_names': ['dummy1'],
- 'inventory_hostname': 'host2',
- '2otherlist__merge_var': {
- 'var': [{'item5': 'value5', 'item6': 'value6'}]
- }
- },
- 'host3': {
- 'group_names': ['dummy2'],
- 'inventory_hostname': 'host3',
- '3otherlist__merge_var': {
- 'var': [{'item3': 'value3', 'item4': 'value4'}]
- }
+ hostvars = self.HostVarsMock({
+ 'host1': {
+ 'group_names': ['dummy1'],
+ 'inventory_hostname': 'host1',
+ '1testlist__merge_var': {
+ 'var': [{'item1': 'value1', 'item2': 'value2'}]
+ }
+ },
+ 'host2': {
+ 'group_names': ['dummy1'],
+ 'inventory_hostname': 'host2',
+ '2otherlist__merge_var': {
+ 'var': [{'item5': 'value5', 'item6': 'value6'}]
+ }
+ },
+ 'host3': {
+ 'group_names': ['dummy2'],
+ 'inventory_hostname': 'host3',
+ '3otherlist__merge_var': {
+ 'var': [{'item3': 'value3', 'item4': 'value4'}]
}
}
})
+ variables = {
+ 'inventory_hostname': 'host1',
+ 'hostvars': hostvars
+ }
+
+ results = self.merge_vars_lookup.run(['__merge_var'], variables)
self.assertEqual(results, [
{'var': [
@@ -216,32 +233,34 @@ class TestMergeVariablesLookup(unittest.TestCase):
{'var': [{'item5': 'value5', 'item6': 'value6'}]},
])
def test_merge_dict_group_multiple(self, mock_set_options, mock_get_option, mock_template):
- results = self.merge_vars_lookup.run(['__merge_var'], {
- 'inventory_hostname': 'host1',
- 'hostvars': {
- 'host1': {
- 'group_names': ['dummy1'],
- 'inventory_hostname': 'host1',
- '1testlist__merge_var': {
- 'var': [{'item1': 'value1', 'item2': 'value2'}]
- }
- },
- 'host2': {
- 'group_names': ['dummy2'],
- 'inventory_hostname': 'host2',
- '2otherlist__merge_var': {
- 'var': [{'item5': 'value5', 'item6': 'value6'}]
- }
- },
- 'host3': {
- 'group_names': ['dummy3'],
- 'inventory_hostname': 'host3',
- '3otherlist__merge_var': {
- 'var': [{'item3': 'value3', 'item4': 'value4'}]
- }
+ hostvars = self.HostVarsMock({
+ 'host1': {
+ 'group_names': ['dummy1'],
+ 'inventory_hostname': 'host1',
+ '1testlist__merge_var': {
+ 'var': [{'item1': 'value1', 'item2': 'value2'}]
+ }
+ },
+ 'host2': {
+ 'group_names': ['dummy2'],
+ 'inventory_hostname': 'host2',
+ '2otherlist__merge_var': {
+ 'var': [{'item5': 'value5', 'item6': 'value6'}]
+ }
+ },
+ 'host3': {
+ 'group_names': ['dummy3'],
+ 'inventory_hostname': 'host3',
+ '3otherlist__merge_var': {
+ 'var': [{'item3': 'value3', 'item4': 'value4'}]
}
}
})
+ variables = {
+ 'inventory_hostname': 'host1',
+ 'hostvars': hostvars
+ }
+ results = self.merge_vars_lookup.run(['__merge_var'], variables)
self.assertEqual(results, [
{'var': [
@@ -257,26 +276,27 @@ class TestMergeVariablesLookup(unittest.TestCase):
['item5'],
])
def test_merge_list_group_multiple(self, mock_set_options, mock_get_option, mock_template):
- print()
- results = self.merge_vars_lookup.run(['__merge_var'], {
- 'inventory_hostname': 'host1',
- 'hostvars': {
- 'host1': {
- 'group_names': ['dummy1'],
- 'inventory_hostname': 'host1',
- '1testlist__merge_var': ['item1']
- },
- 'host2': {
- 'group_names': ['dummy2'],
- 'inventory_hostname': 'host2',
- '2otherlist__merge_var': ['item5']
- },
- 'host3': {
- 'group_names': ['dummy3'],
- 'inventory_hostname': 'host3',
- '3otherlist__merge_var': ['item3']
- }
+ hostvars = self.HostVarsMock({
+ 'host1': {
+ 'group_names': ['dummy1'],
+ 'inventory_hostname': 'host1',
+ '1testlist__merge_var': ['item1']
+ },
+ 'host2': {
+ 'group_names': ['dummy2'],
+ 'inventory_hostname': 'host2',
+ '2otherlist__merge_var': ['item5']
+ },
+ 'host3': {
+ 'group_names': ['dummy3'],
+ 'inventory_hostname': 'host3',
+ '3otherlist__merge_var': ['item3']
}
})
+ variables = {
+ 'inventory_hostname': 'host1',
+ 'hostvars': hostvars
+ }
+ results = self.merge_vars_lookup.run(['__merge_var'], variables)
self.assertEqual(results, [['item1', 'item5']])
diff --git a/ansible_collections/community/general/tests/unit/plugins/module_utils/test_cmd_runner.py b/ansible_collections/community/general/tests/unit/plugins/module_utils/test_cmd_runner.py
index 86576e8ce..6816afb34 100644
--- a/ansible_collections/community/general/tests/unit/plugins/module_utils/test_cmd_runner.py
+++ b/ansible_collections/community/general/tests/unit/plugins/module_utils/test_cmd_runner.py
@@ -7,6 +7,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from sys import version_info
+from functools import partial
import pytest
@@ -15,55 +16,64 @@ from ansible_collections.community.general.plugins.module_utils.cmd_runner impor
TC_FORMATS = dict(
- simple_boolean__true=(cmd_runner_fmt.as_bool, ("--superflag",), True, ["--superflag"]),
- simple_boolean__false=(cmd_runner_fmt.as_bool, ("--superflag",), False, []),
- simple_boolean__none=(cmd_runner_fmt.as_bool, ("--superflag",), None, []),
- simple_boolean_both__true=(cmd_runner_fmt.as_bool, ("--superflag", "--falseflag"), True, ["--superflag"]),
- simple_boolean_both__false=(cmd_runner_fmt.as_bool, ("--superflag", "--falseflag"), False, ["--falseflag"]),
- simple_boolean_both__none=(cmd_runner_fmt.as_bool, ("--superflag", "--falseflag"), None, ["--falseflag"]),
- simple_boolean_both__none_ig=(cmd_runner_fmt.as_bool, ("--superflag", "--falseflag", True), None, []),
- simple_boolean_not__true=(cmd_runner_fmt.as_bool_not, ("--superflag",), True, []),
- simple_boolean_not__false=(cmd_runner_fmt.as_bool_not, ("--superflag",), False, ["--superflag"]),
- simple_boolean_not__none=(cmd_runner_fmt.as_bool_not, ("--superflag",), None, ["--superflag"]),
- simple_optval__str=(cmd_runner_fmt.as_optval, ("-t",), "potatoes", ["-tpotatoes"]),
- simple_optval__int=(cmd_runner_fmt.as_optval, ("-t",), 42, ["-t42"]),
- simple_opt_val__str=(cmd_runner_fmt.as_opt_val, ("-t",), "potatoes", ["-t", "potatoes"]),
- simple_opt_val__int=(cmd_runner_fmt.as_opt_val, ("-t",), 42, ["-t", "42"]),
- simple_opt_eq_val__str=(cmd_runner_fmt.as_opt_eq_val, ("--food",), "potatoes", ["--food=potatoes"]),
- simple_opt_eq_val__int=(cmd_runner_fmt.as_opt_eq_val, ("--answer",), 42, ["--answer=42"]),
- simple_list_potato=(cmd_runner_fmt.as_list, (), "literal_potato", ["literal_potato"]),
- simple_list_42=(cmd_runner_fmt.as_list, (), 42, ["42"]),
- simple_map=(cmd_runner_fmt.as_map, ({'a': 1, 'b': 2, 'c': 3},), 'b', ["2"]),
- simple_default_type__list=(cmd_runner_fmt.as_default_type, ("list",), [1, 2, 3, 5, 8], ["--1", "--2", "--3", "--5", "--8"]),
- simple_default_type__bool_true=(cmd_runner_fmt.as_default_type, ("bool", "what"), True, ["--what"]),
- simple_default_type__bool_false=(cmd_runner_fmt.as_default_type, ("bool", "what"), False, []),
- simple_default_type__potato=(cmd_runner_fmt.as_default_type, ("any-other-type", "potato"), "42", ["--potato", "42"]),
- simple_fixed_true=(cmd_runner_fmt.as_fixed, [("--always-here", "--forever")], True, ["--always-here", "--forever"]),
- simple_fixed_false=(cmd_runner_fmt.as_fixed, [("--always-here", "--forever")], False, ["--always-here", "--forever"]),
- simple_fixed_none=(cmd_runner_fmt.as_fixed, [("--always-here", "--forever")], None, ["--always-here", "--forever"]),
- simple_fixed_str=(cmd_runner_fmt.as_fixed, [("--always-here", "--forever")], "something", ["--always-here", "--forever"]),
+ simple_boolean__true=(partial(cmd_runner_fmt.as_bool, "--superflag"), True, ["--superflag"], None),
+ simple_boolean__false=(partial(cmd_runner_fmt.as_bool, "--superflag"), False, [], None),
+ simple_boolean__none=(partial(cmd_runner_fmt.as_bool, "--superflag"), None, [], None),
+ simple_boolean_both__true=(partial(cmd_runner_fmt.as_bool, "--superflag", "--falseflag"), True, ["--superflag"], None),
+ simple_boolean_both__false=(partial(cmd_runner_fmt.as_bool, "--superflag", "--falseflag"), False, ["--falseflag"], None),
+ simple_boolean_both__none=(partial(cmd_runner_fmt.as_bool, "--superflag", "--falseflag"), None, ["--falseflag"], None),
+ simple_boolean_both__none_ig=(partial(cmd_runner_fmt.as_bool, "--superflag", "--falseflag", True), None, [], None),
+ simple_boolean_not__true=(partial(cmd_runner_fmt.as_bool_not, "--superflag"), True, [], None),
+ simple_boolean_not__false=(partial(cmd_runner_fmt.as_bool_not, "--superflag"), False, ["--superflag"], None),
+ simple_boolean_not__none=(partial(cmd_runner_fmt.as_bool_not, "--superflag"), None, ["--superflag"], None),
+ simple_optval__str=(partial(cmd_runner_fmt.as_optval, "-t"), "potatoes", ["-tpotatoes"], None),
+ simple_optval__int=(partial(cmd_runner_fmt.as_optval, "-t"), 42, ["-t42"], None),
+ simple_opt_val__str=(partial(cmd_runner_fmt.as_opt_val, "-t"), "potatoes", ["-t", "potatoes"], None),
+ simple_opt_val__int=(partial(cmd_runner_fmt.as_opt_val, "-t"), 42, ["-t", "42"], None),
+ simple_opt_eq_val__str=(partial(cmd_runner_fmt.as_opt_eq_val, "--food"), "potatoes", ["--food=potatoes"], None),
+ simple_opt_eq_val__int=(partial(cmd_runner_fmt.as_opt_eq_val, "--answer"), 42, ["--answer=42"], None),
+ simple_list_potato=(cmd_runner_fmt.as_list, "literal_potato", ["literal_potato"], None),
+ simple_list_42=(cmd_runner_fmt.as_list, 42, ["42"], None),
+ simple_list_min_len_ok=(partial(cmd_runner_fmt.as_list, min_len=1), 42, ["42"], None),
+ simple_list_min_len_fail=(partial(cmd_runner_fmt.as_list, min_len=10), 42, None, ValueError),
+ simple_list_max_len_ok=(partial(cmd_runner_fmt.as_list, max_len=1), 42, ["42"], None),
+ simple_list_max_len_fail=(partial(cmd_runner_fmt.as_list, max_len=2), [42, 42, 42], None, ValueError),
+ simple_map=(partial(cmd_runner_fmt.as_map, {'a': 1, 'b': 2, 'c': 3}), 'b', ["2"], None),
+ simple_default_type__list=(partial(cmd_runner_fmt.as_default_type, "list"), [1, 2, 3, 5, 8], ["--1", "--2", "--3", "--5", "--8"], None),
+ simple_default_type__bool_true=(partial(cmd_runner_fmt.as_default_type, "bool", "what"), True, ["--what"], None),
+ simple_default_type__bool_false=(partial(cmd_runner_fmt.as_default_type, "bool", "what"), False, [], None),
+ simple_default_type__potato=(partial(cmd_runner_fmt.as_default_type, "any-other-type", "potato"), "42", ["--potato", "42"], None),
+ simple_fixed_true=(partial(cmd_runner_fmt.as_fixed, ["--always-here", "--forever"]), True, ["--always-here", "--forever"], None),
+ simple_fixed_false=(partial(cmd_runner_fmt.as_fixed, ["--always-here", "--forever"]), False, ["--always-here", "--forever"], None),
+ simple_fixed_none=(partial(cmd_runner_fmt.as_fixed, ["--always-here", "--forever"]), None, ["--always-here", "--forever"], None),
+ simple_fixed_str=(partial(cmd_runner_fmt.as_fixed, ["--always-here", "--forever"]), "something", ["--always-here", "--forever"], None),
)
if tuple(version_info) >= (3, 1):
from collections import OrderedDict
# needs OrderedDict to provide a consistent key order
TC_FORMATS["simple_default_type__dict"] = ( # type: ignore
- cmd_runner_fmt.as_default_type,
- ("dict",),
+ partial(cmd_runner_fmt.as_default_type, "dict"),
OrderedDict((('a', 1), ('b', 2))),
- ["--a=1", "--b=2"]
+ ["--a=1", "--b=2"],
+ None
)
TC_FORMATS_IDS = sorted(TC_FORMATS.keys())
-@pytest.mark.parametrize('func, fmt_opt, value, expected',
+@pytest.mark.parametrize('func, value, expected, exception',
(TC_FORMATS[tc] for tc in TC_FORMATS_IDS),
ids=TC_FORMATS_IDS)
-def test_arg_format(func, fmt_opt, value, expected):
- fmt_func = func(*fmt_opt)
- actual = fmt_func(value, ctx_ignore_none=True)
- print("formatted string = {0}".format(actual))
- assert actual == expected, "actual = {0}".format(actual)
+def test_arg_format(func, value, expected, exception):
+ fmt_func = func()
+ try:
+ actual = fmt_func(value, ctx_ignore_none=True)
+ print("formatted string = {0}".format(actual))
+ assert actual == expected, "actual = {0}".format(actual)
+ except Exception as e:
+ if exception is None:
+ raise
+ assert isinstance(e, exception)
TC_RUNNER = dict(
diff --git a/ansible_collections/community/general/tests/unit/plugins/module_utils/test_python_runner.py b/ansible_collections/community/general/tests/unit/plugins/module_utils/test_python_runner.py
new file mode 100644
index 000000000..015065bdd
--- /dev/null
+++ b/ansible_collections/community/general/tests/unit/plugins/module_utils/test_python_runner.py
@@ -0,0 +1,223 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2024, Alexei Znamensky <russoz@gmail.com>
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+
+import pytest
+
+from ansible_collections.community.general.tests.unit.compat.mock import MagicMock, PropertyMock
+from ansible_collections.community.general.plugins.module_utils.cmd_runner import cmd_runner_fmt
+from ansible_collections.community.general.plugins.module_utils.python_runner import PythonRunner
+
+
+TC_RUNNER = dict(
+ # SAMPLE: This shows all possible elements of a test case. It does not actually run.
+ #
+ # testcase_name=(
+ # # input
+ # dict(
+ # args_bundle = dict(
+ # param1=dict(
+ # type="int",
+ # value=11,
+ # fmt_func=cmd_runner_fmt.as_opt_eq_val,
+ # fmt_arg="--answer",
+ # ),
+ # param2=dict(
+ # fmt_func=cmd_runner_fmt.as_bool,
+ # fmt_arg="--bb-here",
+ # )
+ # ),
+ # runner_init_args = dict(
+ # command="testing",
+ # default_args_order=(),
+ # check_rc=False,
+ # force_lang="C",
+ # path_prefix=None,
+ # environ_update=None,
+ # ),
+ # runner_ctx_args = dict(
+ # args_order=['aa', 'bb'],
+ # output_process=None,
+ # ignore_value_none=True,
+ # ),
+ # ),
+ # # command execution
+ # dict(
+ # runner_ctx_run_args = dict(bb=True),
+ # rc = 0,
+ # out = "",
+ # err = "",
+ # ),
+ # # expected
+ # dict(
+ # results=(),
+ # run_info=dict(
+ # cmd=['/mock/bin/testing', '--answer=11', '--bb-here'],
+ # environ_update={'LANGUAGE': 'C', 'LC_ALL': 'C'},
+ # ),
+ # exc=None,
+ # ),
+ # ),
+ #
+ aa_bb=(
+ dict(
+ args_bundle=dict(
+ aa=dict(type="int", value=11, fmt_func=cmd_runner_fmt.as_opt_eq_val, fmt_arg="--answer"),
+ bb=dict(fmt_func=cmd_runner_fmt.as_bool, fmt_arg="--bb-here"),
+ ),
+ runner_init_args=dict(command="testing"),
+ runner_ctx_args=dict(args_order=['aa', 'bb']),
+ ),
+ dict(runner_ctx_run_args=dict(bb=True), rc=0, out="", err=""),
+ dict(
+ run_info=dict(
+ cmd=['/mock/bin/python', 'testing', '--answer=11', '--bb-here'],
+ environ_update={'LANGUAGE': 'C', 'LC_ALL': 'C'},
+ args_order=('aa', 'bb'),
+ ),
+ ),
+ ),
+ aa_bb_py3=(
+ dict(
+ args_bundle=dict(
+ aa=dict(type="int", value=11, fmt_func=cmd_runner_fmt.as_opt_eq_val, fmt_arg="--answer"),
+ bb=dict(fmt_func=cmd_runner_fmt.as_bool, fmt_arg="--bb-here"),
+ ),
+ runner_init_args=dict(command="toasting", python="python3"),
+ runner_ctx_args=dict(args_order=['aa', 'bb']),
+ ),
+ dict(runner_ctx_run_args=dict(bb=True), rc=0, out="", err=""),
+ dict(
+ run_info=dict(
+ cmd=['/mock/bin/python3', 'toasting', '--answer=11', '--bb-here'],
+ environ_update={'LANGUAGE': 'C', 'LC_ALL': 'C'},
+ args_order=('aa', 'bb'),
+ ),
+ ),
+ ),
+ aa_bb_abspath=(
+ dict(
+ args_bundle=dict(
+ aa=dict(type="int", value=11, fmt_func=cmd_runner_fmt.as_opt_eq_val, fmt_arg="--answer"),
+ bb=dict(fmt_func=cmd_runner_fmt.as_bool, fmt_arg="--bb-here"),
+ ),
+ runner_init_args=dict(command="toasting", python="/crazy/local/bin/python3"),
+ runner_ctx_args=dict(args_order=['aa', 'bb']),
+ ),
+ dict(runner_ctx_run_args=dict(bb=True), rc=0, out="", err=""),
+ dict(
+ run_info=dict(
+ cmd=['/crazy/local/bin/python3', 'toasting', '--answer=11', '--bb-here'],
+ environ_update={'LANGUAGE': 'C', 'LC_ALL': 'C'},
+ args_order=('aa', 'bb'),
+ ),
+ ),
+ ),
+ aa_bb_venv=(
+ dict(
+ args_bundle=dict(
+ aa=dict(type="int", value=11, fmt_func=cmd_runner_fmt.as_opt_eq_val, fmt_arg="--answer"),
+ bb=dict(fmt_func=cmd_runner_fmt.as_bool, fmt_arg="--bb-here"),
+ ),
+ runner_init_args=dict(command="toasting", venv="/venv"),
+ runner_ctx_args=dict(args_order=['aa', 'bb']),
+ ),
+ dict(runner_ctx_run_args=dict(bb=True), rc=0, out="", err=""),
+ dict(
+ run_info=dict(
+ cmd=['/venv/bin/python', 'toasting', '--answer=11', '--bb-here'],
+ environ_update={'LANGUAGE': 'C', 'LC_ALL': 'C', 'VIRTUAL_ENV': '/venv', 'PATH': '/venv/bin'},
+ args_order=('aa', 'bb'),
+ ),
+ ),
+ ),
+)
+TC_RUNNER_IDS = sorted(TC_RUNNER.keys())
+
+
+@pytest.mark.parametrize('runner_input, cmd_execution, expected',
+ (TC_RUNNER[tc] for tc in TC_RUNNER_IDS),
+ ids=TC_RUNNER_IDS)
+def test_runner_context(runner_input, cmd_execution, expected):
+ arg_spec = {}
+ params = {}
+ arg_formats = {}
+ for k, v in runner_input['args_bundle'].items():
+ try:
+ arg_spec[k] = {'type': v['type']}
+ except KeyError:
+ pass
+ try:
+ params[k] = v['value']
+ except KeyError:
+ pass
+ try:
+ arg_formats[k] = v['fmt_func'](v['fmt_arg'])
+ except KeyError:
+ pass
+
+ orig_results = tuple(cmd_execution[x] for x in ('rc', 'out', 'err'))
+
+ print("arg_spec={0}\nparams={1}\narg_formats={2}\n".format(
+ arg_spec,
+ params,
+ arg_formats,
+ ))
+
+ module = MagicMock()
+ type(module).argument_spec = PropertyMock(return_value=arg_spec)
+ type(module).params = PropertyMock(return_value=params)
+ module.get_bin_path.return_value = os.path.join(
+ runner_input["runner_init_args"].get("venv", "/mock"),
+ "bin",
+ runner_input["runner_init_args"].get("python", "python")
+ )
+ module.run_command.return_value = orig_results
+
+ runner = PythonRunner(
+ module=module,
+ arg_formats=arg_formats,
+ **runner_input['runner_init_args']
+ )
+
+ def _extract_path(run_info):
+ path = run_info.get("environ_update", {}).get("PATH")
+ if path is not None:
+ run_info["environ_update"] = dict((k, v)
+ for k, v in run_info["environ_update"].items()
+ if k != "PATH")
+ return run_info, path
+
+ def _assert_run_info_env_path(actual, expected):
+ actual2 = set(actual.split(":"))
+ assert expected in actual2, "Missing expected path {0} in output PATH: {1}".format(expected, actual)
+
+ def _assert_run_info(actual, expected):
+ reduced = dict((k, actual[k]) for k in expected.keys())
+ reduced, act_path = _extract_path(reduced)
+ expected, exp_path = _extract_path(expected)
+ if exp_path is not None:
+ _assert_run_info_env_path(act_path, exp_path)
+ assert reduced == expected, "{0}".format(reduced)
+
+ def _assert_run(expected, ctx, results):
+ _assert_run_info(ctx.run_info, expected['run_info'])
+ assert results == expected.get('results', orig_results)
+
+ exc = expected.get("exc")
+ if exc:
+ with pytest.raises(exc):
+ with runner.context(**runner_input['runner_ctx_args']) as ctx:
+ results = ctx.run(**cmd_execution['runner_ctx_run_args'])
+ _assert_run(expected, ctx, results)
+
+ else:
+ with runner.context(**runner_input['runner_ctx_args']) as ctx:
+ results = ctx.run(**cmd_execution['runner_ctx_run_args'])
+ _assert_run(expected, ctx, results)
diff --git a/ansible_collections/community/general/tests/unit/plugins/modules/helper.py b/ansible_collections/community/general/tests/unit/plugins/modules/helper.py
index a7322bf4d..e012980af 100644
--- a/ansible_collections/community/general/tests/unit/plugins/modules/helper.py
+++ b/ansible_collections/community/general/tests/unit/plugins/modules/helper.py
@@ -9,7 +9,6 @@ __metaclass__ = type
import sys
import json
from collections import namedtuple
-from itertools import chain, repeat
import pytest
import yaml
@@ -52,9 +51,9 @@ class _BaseContext(object):
test_flags = self.test_flags()
if test_flags.get("skip"):
- pytest.skip()
+ pytest.skip(test_flags.get("skip"))
if test_flags.get("xfail"):
- pytest.xfail()
+ pytest.xfail(test_flags.get("xfail"))
func()
@@ -76,12 +75,21 @@ class _RunCmdContext(_BaseContext):
self.mock_run_cmd = self._make_mock_run_cmd()
def _make_mock_run_cmd(self):
- call_results = [(x.rc, x.out, x.err) for x in self.run_cmd_calls]
- error_call_results = (123,
- "OUT: testcase has not enough run_command calls",
- "ERR: testcase has not enough run_command calls")
+ def _results():
+ for result in [(x.rc, x.out, x.err) for x in self.run_cmd_calls]:
+ yield result
+ raise Exception("testcase has not enough run_command calls")
+
+ results = _results()
+
+ def side_effect(self_, **kwargs):
+ result = next(results)
+ if kwargs.get("check_rc", False) and result[0] != 0:
+ raise Exception("rc = {0}".format(result[0]))
+ return result
+
mock_run_command = self.mocker.patch('ansible.module_utils.basic.AnsibleModule.run_command',
- side_effect=chain(call_results, repeat(error_call_results)))
+ side_effect=side_effect)
return mock_run_command
def check_results(self, results):
diff --git a/ansible_collections/community/general/tests/unit/plugins/modules/test_cpanm.yaml b/ansible_collections/community/general/tests/unit/plugins/modules/test_cpanm.yaml
index 3ed718d48..4eed95720 100644
--- a/ansible_collections/community/general/tests/unit/plugins/modules/test_cpanm.yaml
+++ b/ansible_collections/community/general/tests/unit/plugins/modules/test_cpanm.yaml
@@ -7,6 +7,7 @@
- id: install_dancer_compatibility
input:
name: Dancer
+ mode: compatibility
output:
changed: true
run_command_calls:
@@ -23,6 +24,7 @@
- id: install_dancer_already_installed_compatibility
input:
name: Dancer
+ mode: compatibility
output:
changed: false
run_command_calls:
@@ -34,7 +36,6 @@
- id: install_dancer
input:
name: Dancer
- mode: new
output:
changed: true
run_command_calls:
@@ -46,6 +47,7 @@
- id: install_distribution_file_compatibility
input:
name: MIYAGAWA/Plack-0.99_05.tar.gz
+ mode: compatibility
output:
changed: true
run_command_calls:
@@ -57,7 +59,6 @@
- id: install_distribution_file
input:
name: MIYAGAWA/Plack-0.99_05.tar.gz
- mode: new
output:
changed: true
run_command_calls:
diff --git a/ansible_collections/community/general/tests/unit/plugins/modules/test_django_command.py b/ansible_collections/community/general/tests/unit/plugins/modules/test_django_command.py
new file mode 100644
index 000000000..ffa9feb39
--- /dev/null
+++ b/ansible_collections/community/general/tests/unit/plugins/modules/test_django_command.py
@@ -0,0 +1,13 @@
+# Copyright (c) Alexei Znamensky (russoz@gmail.com)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+from ansible_collections.community.general.plugins.modules import django_command
+from .helper import Helper
+
+
+Helper.from_module(django_command, __name__)
diff --git a/ansible_collections/community/general/tests/unit/plugins/modules/test_django_command.yaml b/ansible_collections/community/general/tests/unit/plugins/modules/test_django_command.yaml
new file mode 100644
index 000000000..046dd87f0
--- /dev/null
+++ b/ansible_collections/community/general/tests/unit/plugins/modules/test_django_command.yaml
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) Alexei Znamensky (russoz@gmail.com)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+---
+- id: command_success
+ input:
+ command: check
+ extra_args:
+ - babaloo
+ - yaba
+ - daba
+ - doo
+ settings: whatever.settings
+ run_command_calls:
+ - command: [/testbin/python, -m, django, check, --no-color, --settings=whatever.settings, babaloo, yaba, daba, doo]
+ environ: &env-def {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
+ rc: 0
+ out: "whatever\n"
+ err: ""
+- id: command_fail
+ input:
+ command: check
+ extra_args:
+ - babaloo
+ - yaba
+ - daba
+ - doo
+ settings: whatever.settings
+ output:
+ failed: true
+ run_command_calls:
+ - command: [/testbin/python, -m, django, check, --no-color, --settings=whatever.settings, babaloo, yaba, daba, doo]
+ environ: *env-def
+ rc: 1
+ out: "whatever\n"
+ err: ""
diff --git a/ansible_collections/community/general/tests/unit/plugins/modules/test_homebrew.py b/ansible_collections/community/general/tests/unit/plugins/modules/test_homebrew.py
index f849b433d..d04ca4de5 100644
--- a/ansible_collections/community/general/tests/unit/plugins/modules/test_homebrew.py
+++ b/ansible_collections/community/general/tests/unit/plugins/modules/test_homebrew.py
@@ -2,23 +2,28 @@
# 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)
+from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.general.tests.unit.compat import unittest
-from ansible_collections.community.general.plugins.modules.homebrew import Homebrew
+from ansible_collections.community.general.plugins.module_utils.homebrew import HomebrewValidate
class TestHomebrewModule(unittest.TestCase):
def setUp(self):
- self.brew_app_names = [
- 'git-ssh',
- 'awscli@1',
- 'bash'
+ self.brew_app_names = ["git-ssh", "awscli@1", "bash"]
+
+ self.invalid_names = [
+ "git ssh",
+ "git*",
]
def test_valid_package_names(self):
for name in self.brew_app_names:
- self.assertTrue(Homebrew.valid_package(name))
+ self.assertTrue(HomebrewValidate.valid_package(name))
+
+ def test_invalid_package_names(self):
+ for name in self.invalid_names:
+ self.assertFalse(HomebrewValidate.valid_package(name))
diff --git a/ansible_collections/community/general/tests/unit/plugins/modules/test_puppet.yaml b/ansible_collections/community/general/tests/unit/plugins/modules/test_puppet.yaml
index 308be9797..7909403cf 100644
--- a/ansible_collections/community/general/tests/unit/plugins/modules/test_puppet.yaml
+++ b/ansible_collections/community/general/tests/unit/plugins/modules/test_puppet.yaml
@@ -190,3 +190,35 @@
rc: 0
out: ""
err: ""
+- id: puppet_agent_waitforlock
+ input:
+ waitforlock: 30
+ output:
+ changed: false
+ run_command_calls:
+ - command: [/testbin/puppet, config, print, agent_disabled_lockfile]
+ environ: *env-def
+ rc: 0
+ out: "blah, anything"
+ err: ""
+ - command:
+ - /testbin/timeout
+ - -s
+ - "9"
+ - 30m
+ - /testbin/puppet
+ - agent
+ - --onetime
+ - --no-daemonize
+ - --no-usecacheonfailure
+ - --no-splay
+ - --detailed-exitcodes
+ - --verbose
+ - --color
+ - "0"
+ - --waitforlock
+ - "30"
+ environ: *env-def
+ rc: 0
+ out: ""
+ err: ""
diff --git a/ansible_collections/community/general/tests/unit/plugins/plugin_utils/test_unsafe.py b/ansible_collections/community/general/tests/unit/plugins/plugin_utils/test_unsafe.py
new file mode 100644
index 000000000..3f35ee933
--- /dev/null
+++ b/ansible_collections/community/general/tests/unit/plugins/plugin_utils/test_unsafe.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2024, Felix Fontein <felix@fontein.de>
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+import pytest
+
+from ansible.utils.unsafe_proxy import AnsibleUnsafe
+
+from ansible_collections.community.general.plugins.plugin_utils.unsafe import (
+ make_unsafe,
+)
+
+
+TEST_MAKE_UNSAFE = [
+ (
+ u'text',
+ [],
+ [
+ (),
+ ],
+ ),
+ (
+ u'{{text}}',
+ [
+ (),
+ ],
+ [],
+ ),
+ (
+ b'text',
+ [],
+ [
+ (),
+ ],
+ ),
+ (
+ b'{{text}}',
+ [
+ (),
+ ],
+ [],
+ ),
+ (
+ {
+ 'skey': 'value',
+ 'ukey': '{{value}}',
+ 1: [
+ 'value',
+ '{{value}}',
+ {
+ 1.0: '{{value}}',
+ 2.0: 'value',
+ },
+ ],
+ },
+ [
+ ('ukey', ),
+ (1, 1),
+ (1, 2, 1.0),
+ ],
+ [
+ ('skey', ),
+ (1, 0),
+ (1, 2, 2.0),
+ ],
+ ),
+ (
+ ['value', '{{value}}'],
+ [
+ (1, ),
+ ],
+ [
+ (0, ),
+ ],
+ ),
+]
+
+
+@pytest.mark.parametrize("value, check_unsafe_paths, check_safe_paths", TEST_MAKE_UNSAFE)
+def test_make_unsafe(value, check_unsafe_paths, check_safe_paths):
+ unsafe_value = make_unsafe(value)
+ assert unsafe_value == value
+ for check_path in check_unsafe_paths:
+ obj = unsafe_value
+ for elt in check_path:
+ obj = obj[elt]
+ assert isinstance(obj, AnsibleUnsafe)
+ for check_path in check_safe_paths:
+ obj = unsafe_value
+ for elt in check_path:
+ obj = obj[elt]
+ assert not isinstance(obj, AnsibleUnsafe)
+
+
+def test_make_unsafe_dict_key():
+ value = {
+ b'test': 1,
+ u'test': 2,
+ }
+ unsafe_value = make_unsafe(value)
+ assert unsafe_value == value
+ for obj in unsafe_value:
+ assert not isinstance(obj, AnsibleUnsafe)
+
+ value = {
+ b'{{test}}': 1,
+ u'{{test}}': 2,
+ }
+ unsafe_value = make_unsafe(value)
+ assert unsafe_value == value
+ for obj in unsafe_value:
+ assert isinstance(obj, AnsibleUnsafe)
+
+
+def test_make_unsafe_set():
+ value = set([b'test', u'test'])
+ unsafe_value = make_unsafe(value)
+ assert unsafe_value == value
+ for obj in unsafe_value:
+ assert not isinstance(obj, AnsibleUnsafe)
+
+ value = set([b'{{test}}', u'{{test}}'])
+ unsafe_value = make_unsafe(value)
+ assert unsafe_value == value
+ for obj in unsafe_value:
+ assert isinstance(obj, AnsibleUnsafe)